import React, {Component} from 'react';
import PropTypes from 'prop-types';
import './base-style/SshInput.css'

class SshInput extends Component {

    constructor(props) {
        super(props)
        this.state = {
            isValid: true,
            errorMsg: '',
            isValidating: false
        }
    }

    parseValid = () => {
        return new Promise((resolve, reject) => {
            let {rules, value} = this.props
            let validResultArr = []
            let validNum = 0
            if (!rules || !rules.length) {
                return true
            }

            // 过滤无效规则
            rules = rules.filter(rule => {
                return rule.required || rule.validator
            })

            // 根据结果数组渲染视图
            const finalValid = () => {
                // 确保渲染视图的时候所有校验规则都调用完毕
                if (validNum !== rules.length) return
                let resultValid = true
                let resultErrorMsg = ''

                for (let i = 0, len = validResultArr.length; i < len; i++) {
                    const validResult = validResultArr[i]
                    if (!validResult.valid) {
                        resultValid = false
                        resultErrorMsg = validResult.errorMsg
                        break
                    }
                }
                clearTimeout(this.timer)
                this.setState({
                    isValid: resultValid,
                    errorMsg: resultErrorMsg,
                    isValidating: false
                })
                resultValid ? resolve() : reject()
            }

            rules.forEach(rule => {
                if (rule.required) {
                    validNum++
                    let errorMsg = rule.message || ''
                    let valid = !!this.props.value.trim()
                    validResultArr.push({valid, errorMsg})
                    finalValid()
                }
                if (rule.validator) {
                    validNum++
                    this.setState({
                        isValidating: true
                    })
                    const callBack = (e) => {
                        let valid = false
                        let errorMsg = ''
                        this.setState({
                            isValidating: false
                        })
                        if (!e) {
                            valid = true
                        } else {
                            valid = false
                            errorMsg = e.message
                        }
                        validResultArr.push({valid, errorMsg})
                        finalValid()
                    }
                    clearTimeout(this.timer)
                    this.timer = setTimeout(() => {
                        rule.validator(value, callBack)
                    }, 200)
                }
            })


        })
    }

    clearFormValid = () => {
        this.setState({
            isValidating: false,
            isValid: true,
            errorMsg: ''
        })
    }

    handleChange = (e) => {
        const value = e.target.value
        const {onChange} = this.props
        onChange && onChange(value)
        // 外部组件的setState是异步的，在microTask队列中才能获取到props的最新值
        Promise.resolve()
            .then(() => {
                return this.parseValid()
            })
            .catch(() => {

            })
    }

    componentDidMount() {
        const collectValidfn = this.context.collectValidFns
        const collectClearVn = this.context.collectClearValidFns
        collectValidfn && collectValidfn(this.parseValid)
        collectClearVn && collectClearVn(this.clearFormValid)
    }

    render() {
        const {isValid, isValidating, errorMsg} = this.state

        const {className, type} = this.props

        const inputClass = (() => {
            return ['ssh-input', isValid ? '' : 'is-error'].join(' ')
        })()

        const badge = (() => {
            if (isValidating) {
                return <span className="validating-badge">验证中，请稍后...</span>
            }
            if (!isValid) {
                return <span className="error-badge">{errorMsg}</span>
            }
            return ''
        })()

        return (
            <div className={className}>
                {
                    type === 'textarea'
                        ?
                        <textarea
                            {...this.props}
                            onChange={this.handleChange}
                            className={inputClass}
                            spellCheck="false">
                        </textarea>
                        :
                        <input
                            {...this.props}
                            onChange={this.handleChange}
                            className={inputClass}
                        />
                }
                {badge}
            </div>
        )
    }
}

SshInput.contextTypes = {
    collectValidFns: PropTypes.func,
    collectClearValidFns: PropTypes.func
};


export default SshInput